package com.hmy.contract.service.contract.save.supply.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hmy.ccp.error.exception.HMYRuntimeException;
import com.hmy.ccp.starter.web.utils.UserContextUtil;
import com.hmy.contract.common.constant.ContractConstants;
import com.hmy.contract.common.constant.RedisKeyConstants;
import com.hmy.contract.common.properties.LessorInfoProperties;
import com.hmy.contract.common.utils.CommonCodeGenerator;
import com.hmy.contract.commons.enums.ContractBusinessTypeEnum;
import com.hmy.contract.commons.enums.ContractStatusEnum;
import com.hmy.contract.dal.mapper.ContractMapper;
import com.hmy.contract.dal.mapper.SupplyContractMapper;
import com.hmy.contract.dal.po.ContractPo;
import com.hmy.contract.dal.po.SupplyContractPo;
import com.hmy.contract.service.contract.IContractConfigService;
import com.hmy.contract.service.contract.save.supply.ISaveSupplyContractService;
import com.hmy.contract.service.dto.contract.ContractConfigDto;
import com.hmy.contract.service.dto.contract.SupplyOrderDetailDto;
import com.hmy.contract.service.dto.save.SaveSupplyContractDto;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author seven.qi 齐胜南
 * @version 1.0
 * @description
 * @date 2024/3/11 15:33
 */
@Service
public class SaveElectronicSupplyContractService extends SaveSupplyContractBaseService implements ISaveSupplyContractService {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private ContractMapper contractMapper;

    @Resource
    private LessorInfoProperties lessorInfoProperties;

    @Resource
    private IContractConfigService contractConfigService;

    @Resource
    private SupplyContractMapper supplyContractMapper;

    @Resource
    private SupplyContractFieldBuildService supplyContractFieldBuildService;

    @Override
    public void beforeCreate(SaveSupplyContractDto dto) {

    }

    @Override
    public SupplyContractPo save(SaveSupplyContractDto dto) {
        SupplyContractPo supplyContractPo = convertPo(dto);
        supplyContractMapper.insert(supplyContractPo);
        return supplyContractPo;
    }

    private SupplyContractPo convertPo(SaveSupplyContractDto dto) {
        ContractConfigDto contractConfigDto = contractConfigService.checkConfigExist(ContractBusinessTypeEnum.SUPPLY_ELECTRONIC_CONTRACT.getType());
        LambdaQueryWrapper<ContractPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ContractPo::getIsDeleted, Boolean.FALSE);
        wrapper.eq(ContractPo::getOrderId, dto.getSupplyOrderDetail().getOrderId());
        wrapper.in(ContractPo::getBusinessType, ContractBusinessTypeEnum.SALE_PAPER_CONTRACT.getType(), ContractBusinessTypeEnum.SALE_ELECTRONIC_CONTRACT.getType());
        ContractPo contractPo = contractMapper.selectOne(wrapper);
        if (Objects.isNull(contractPo)) {
            throw new HMYRuntimeException(502000034);
        }
        dto.setContractNo(contractPo.getContractNo());
        SupplyContractPo po = new SupplyContractPo();
        SupplyOrderDetailDto supplyOrderDetail = dto.getSupplyOrderDetail();
        po.setOrderId(supplyOrderDetail.getOrderId());
        po.setOrderNo(supplyOrderDetail.getOrderNo());
        po.setContractId(contractPo.getContractId());
        po.setContractName(contractPo.getContractName());
        po.setSupplyOrderId(supplyOrderDetail.getSupplyOrderId());
        po.setSupplyOrderNo(supplyOrderDetail.getSupplyOrderNo());
        po.setRelationId(supplyOrderDetail.getSupplyOrderId());
        po.setRelationNo(supplyOrderDetail.getSupplyOrderNo());
        po.setSupplyContractName(contractConfigDto.getContractName());
        po.setSupplyContractNo(generateContractNo(dto));
        po.setContractNo(contractPo.getContractNo());
        po.setProjectName(supplyOrderDetail.getProjectName());
        po.setOrderDetailExtension(JSONUtil.toJsonStr(supplyOrderDetail));
        po.setLessorName(lessorInfoProperties.getName());
        po.setLessorInfo(JSONUtil.toJsonStr(lessorInfoProperties));
        po.setCustomerId(supplyOrderDetail.getCustomerId());
        po.setCustomerName(supplyOrderDetail.getCustomerName());
        po.setCustomerIdCardNo(supplyOrderDetail.getCustomerContactorIdCardNumber());
        po.setCustomerPhone(supplyOrderDetail.getCustomerContactorPhone());
        po.setCustomerExtension(JSONUtil.toJsonStr(generateCustomerExtension(supplyOrderDetail)));
        po.setAuthorizerInfo(JSONUtil.toJsonStr(supplyOrderDetail.getAuthorizerDetails()));
        po.setSaleManagerId(supplyOrderDetail.getSaleManagerId());
        po.setSaleManagerName(supplyOrderDetail.getSaleManagerName());
        po.setDeptId(supplyOrderDetail.getSaleManagerDepartId());
        po.setContractType(dto.getType());
        po.setStatus(ContractStatusEnum.WAITING_CREATE.getStatus());
        po.setRelationId(supplyOrderDetail.getSupplyOrderId());
        po.setRelationNo(supplyOrderDetail.getSupplyOrderNo());
        po.setBusinessType(ContractBusinessTypeEnum.SUPPLY_ELECTRONIC_CONTRACT.getType());
        po.setTemplateDataDetailExtension(JSONUtil.toJsonStr(addTemplateDataDetailExtension(dto, contractPo)));
        po.setActorDetailExtension(JSONUtil.toJsonStr(addSupplyContractActorDetail(dto)));
        UserContextUtil.initCreatorInfo(po);
        UserContextUtil.initUpdaterInfo(po);
        return po;
    }

    @Override
    public void afterCreate(SaveSupplyContractDto dto) {
        // todo 发起流程

        // todo 调用修改增补订单状态接口
    }

    @Override
    public String generateContractNo(SaveSupplyContractDto dto) {
        //查询主订单下增补订单明细数量
        Integer count = supplyContractMapper.selectCount(
                Wrappers.lambdaQuery(SupplyContractPo.class)
                        .eq(SupplyContractPo::getContractNo, dto.getContractNo())
        );

        AtomicInteger atomicInteger = new AtomicInteger(count);
        String key = String.format("%03d", atomicInteger.incrementAndGet());
        //todo 考虑增补功能使用场景少,并发可能性低,暂不加锁,如果发生并发 后期可考虑使用分布式锁
        return dto.getContractNo() + "-" + key;
    }

}
